

/**
 * @constructor
 * @throws {Error}
 */
function Facade ()
{
	if (Facade.instance != null)
	{
		throw new Error (Facade.SINGLETON_MSG);
	}
	
	Facade.instance= this;
	this.initializeFacade();
};

/**
 * @protected
 * @return {void}
 */
Facade.prototype.initializeFacade= function ()
{
	this.initializeModel();
	this.initializeController();
	this.initializeView();
};

/**
 * @static
 * @return {Facade}
 */
Facade.getInstance= function ()
{
	if (Facade.instance == null)
	{
		Facade.instance= new Facade;
	}
	
	return Facade.instance;
};

/**
 * @protected
 * @return {void}
 */
Facade.prototype.initializeController= function ()
{
	if (this.controller != null)
	{
		return;
	}
	
	this.controller= Controller.getInstance();
};

/**
 * @protected
 * @return {void}
 */
Facade.prototype.initializeModel= function ()
{
	if (this.model != null)
	{
		return;
	}
	
	this.model= Model.getInstance();
};

/**
 * @protected
 * @return {void}
 */
Facade.prototype.initializeView= function ()
{
	if (this.view != null)
	{
		return;
	}
	
	this.view= View.getInstance();
};


/**
 * @param {string} notificationName
 * @param {Function} commandCtorRef
 * @return {void}
 */
Facade.prototype.registerCommand= function (notificationName, commandCtorRef)
{
	this.controller.registerCommand(notificationName, commandCtorRef);
};

/**
 * @param {string} notificationName
 * @return {void}
 */
Facade.prototype.removeCommand= function (notificationName)
{
	this.controller.removeCommand(notificationName);
};

/**
 * @param {string} notificationName
 * @return {boolean}
 */
Facade.prototype.hasCommand= function (notificationName)
{
	return this.controller.hasCommand(notificationName);
};

/**
 * @param {Proxy} proxy
 * @return {void}
 */
Facade.prototype.registerProxy= function (proxy)
{
	this.model.registerProxy(proxy);
};

/**
 * @param {string} proxyName
 * @return {?Proxy}
 */
Facade.prototype.retrieveProxy= function (proxyName)
{
	return this.model.retrieveProxy(proxyName);
};

/**
 * @param {string} proxyName
 * @return {?Proxy}
 */
Facade.prototype.removeProxy= function (proxyName)
{
	var proxy= null;
	if (this.model != null)
	{
		proxy= this.model.removeProxy(proxyName);
	}
	
	return proxy;
};

/**
 * @param {string} proxyName
 * @return {boolean}
 */
Facade.prototype.hasProxy= function (proxyName)
{
	return this.model.hasProxy(proxyName);
};

/**
 * @param {Mediator} mediator
 * @return {void}
 */
Facade.prototype.registerMediator= function (mediator)
{
	if (this.view != null)
	{
		this.view.registerMediator(mediator);
	}
};

/**
 * @param {string} mediatorName
 * @return {?Mediator}
 */
Facade.prototype.retrieveMediator= function (mediatorName)
{
	return this.view.retrieveMediator(mediatorName);
};

/**
 * @param {string} mediatorName
 * @return {?Mediator}
 */
Facade.prototype.removeMediator= function (mediatorName)
{
	var mediator= null;
	if (this.view != null)
	{
		mediator= this.view.removeMediator(mediatorName);
	}
	
	return mediator;
};

/**
 * @param {string} mediatorName
 * @return {boolean}
 */
Facade.prototype.hasMediator= function (mediatorName)
{
	return this.view.hasMediator(mediatorName);
};

/**
 * @param {string} notificationName
 * @param {*} [body]
 * @param {string} [type]
 * @return {void}
 */
Facade.prototype.sendNotification= function (notificationName, body, type)
{
	this.notifyObservers(new Notification(notificationName, body, type));
};

/**
 * @param {Notification} notification
 * @return {void}
 */
Facade.prototype.notifyObservers= function (notification)
{
	if (this.view != null)
	{
		this.view.notifyObservers(notification);
	}
};

/**
 * @protected
 * @type {Controller}
 */
Facade.prototype.controller= null;

/**
 * @protected
 * @type {Model}
 */
Facade.prototype.model= null;

/**
 * @protected
 * @type {View}
 */
Facade.prototype.view= null;

/**
 * @static
 * @protected
 * @type {Facade}
 */
Facade.instance= null;

/**
 * @static
 * @protected
 * @const
 * @type {string}
 */
Facade.SINGLETON_MSG= "Facade Singleton already instantiated";
